#include <vector>
#include <iostream>
#include <string>
#include <any>
#include <string>
#include <thread>
#include <chrono>

#ifdef __GNUC__ 
#include <unistd.h>
#include <signal.h> 
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h> 

struct MAINARGS
{
    int argc;
    char** argv;
};

static MAINARGS gs_args;

void print_args(int argc, char* argv[]);
void print_pid();
int begin_child_proc(int argc, char* argv[]);
void onSignal(int signal);

int main(int argc, char* argv[])
{
    // 记录主函数参数
    gs_args.argc = argc;
    gs_args.argv = argv;

    // 创建子进程
    pid_t pid = fork();
    if (0 == pid)
    {
        // 子进程
        begin_child_proc(argc, argv);
    }
    else if (0 < pid)
    {
        // 父进程
        print_args(argc, argv);
        print_pid();
        signal(SIGCHLD, onSignal);
    }
    else
    {
        // fork 失败
        return -1;
    }

    auto ch = getchar();
    while (true)
    {
        if (ch == 'q')
        {
            std::cout << "parent exit\n";
            break;
        }
        auto ch = getchar();
    }
    return 0;
}

void print_args(int argc, char* argv[])
{
    for (int i = 0; i < argc; ++i)
    {
        std::cout << argv[i] << ' ';
    }
    std::cout << "\n";
}

void print_pid()
{
    std::cout << "pid=" << getpid();
    std::cout << "\tppid=" << getppid();
    std::cout << '\n';
}

int begin_child_proc(int argc, char* argv[])
{
    print_args(argc, argv);
    print_pid();

    // 父进程死亡，自动给子进程发送SIGKILL信号
    prctl(PR_SET_PDEATHSIG, SIGKILL);

    // 休眠5秒后退出
    int i = 5;
    while (i-- > 0)
    {
        std::cout << "i = " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    //子进程正常退出不会被拉起来，crash或者被kill，都会被父进程拉起来
    throw std::runtime_error{ "child process error." };
    // std::cout << "child exit\n";
    return 0;
}

void onSignal(int signal)
{
    std::cout << "onSignal, signal=" << signal << std::endl;
    if (SIGCHLD == signal)
    {
        // 回收子进程资源
        int status = -1;
        while (waitpid(-1, &status, WNOHANG) > 0);

        // 重新拉起子进程 
        if (0 == fork())
        {
            // 子进程
            begin_child_proc(gs_args.argc, gs_args.argv);
        }
    }
}
#endif

#ifdef _WIN32
int main()
{ 
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    return 0;
}
#endif
